package com.niiwoo.civet.trade.service.local.kaola.newrepay;


import com.alibaba.dubbo.config.annotation.Reference;
import com.lycheepay.gateway.client.dto.QueryTradeRecordResultDTO;
import com.niiwoo.activity.stage.enums.prize.UserPrizeUseSceneEnum;
import com.niiwoo.civet.account.dto.common.BankCardDTO;
import com.niiwoo.civet.account.dto.request.AddThirdBillRequestDTO;
import com.niiwoo.civet.account.dto.response.AccountBaseResponse;
import com.niiwoo.civet.account.enums.BillSecondSubjectEnum;
import com.niiwoo.civet.account.enums.BillUserTypeEnum;
import com.niiwoo.civet.account.enums.InoutTypeEnum;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.account.service.NiiwooBillDubboService;
import com.niiwoo.civet.account.service.bankcard.BankCardDubboService;
import com.niiwoo.civet.base.enums.FeeTypeEnum;
import com.niiwoo.civet.trade.constant.PlatformConstant;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.ProjectBorrowerPlanNewDTO;
import com.niiwoo.civet.trade.dto.common.ProjectDynamicDTO;
import com.niiwoo.civet.trade.dto.kaola.Result;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.enums.kaola.KaoLaRepayOrderRepayTypeEnum;
import com.niiwoo.civet.trade.enums.kaola.KaolaRepayOrderRepayStatusEnum;
import com.niiwoo.civet.trade.service.local.kaola.KaoLaLiCaiRepaymentService;
import com.niiwoo.civet.trade.service.local.project.ProjectLocalService;
import com.niiwoo.civet.trade.service.local.refund.CommonLocalService;
import com.niiwoo.civet.trade.service.local.refund.TransDetailLocalService;
import com.niiwoo.civet.trade.service.local.third.ActivityLocalService;
import com.niiwoo.civet.user.dto.request.JPushExtDTO;
import com.niiwoo.civet.user.dto.request.UserLetterRequestDTO;
import com.niiwoo.civet.user.enums.*;
import com.niiwoo.civet.user.service.SendSmsDubboService;
import com.niiwoo.civet.user.service.UserCreditDubboService;
import com.niiwoo.civet.user.service.UserLetterDubboService;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.lanmao.properties.LanMaoProperties;
import com.niiwoo.tripod.rabbitmq.component.ConsistencyRabbitTemplate;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service("kaoLaLiCaiRepayCallbackForKFTService")
@Slf4j
public class KaoLaLiCaiRepayCallbackForKFTService {

    @Autowired
    private ProjectMapperExt projectMapperExt;

    @Autowired
    private ProjectBorrowerSummaryMapperExt projectBorrowerSummaryMapperExt;


    @Autowired
    private ProjectBorrowerPlanNewMapperExt projectBorrowerPlanNewMapperExt;

    @Autowired
    private ProjectBorrowerPlanDetailMapperExt projectBorrowerPlanDetailMapperExt;

    @Autowired
    private ProjectInvestorPlanMapperExt projectInvestorPlanMapperExt;

    @Autowired
    private ProjectCreditorFundMapperExt projectCreditorFundMapper;

    @Autowired
    private ActivityLocalService activityLocalService;

    @Autowired
    private TransDetailLocalService transDetailLocalService;

    @Autowired
    private ProjectLocalService projectLocalService;

    @Reference(version = "1.0.0")
    SendSmsDubboService sendSmsDubboService;

    @Reference(version = "1.0.0")
    UserLetterDubboService userLetterDubboService;


    @Reference(version = "1.0.0")
    BankCardDubboService bankCardDubboService;

    @Reference(version = "1.0.0")
    private UserCreditDubboService userCreditDubboService;

    @Autowired
    private ConsistencyRabbitTemplate consistencyRabbitTemplate;

    @Reference(version = "1.0.0")
    private NiiwooBillDubboService niiwooBillDubboService;

    @Reference(version = "1.0.0")
    private AccountDubboService accountDubboService;

    @Autowired
    KaoLaLiCaiRepaymentService kaoLaLiCaiRepaymentService;
    @Autowired
    private CommonLocalService commonLocalService;


    @Value("${h5-borrow-detail-url}")
    private String h5BorrowDetailUrl;

    @Autowired
    private LanMaoProperties lanMaoProperties;

    @Autowired
    private KaolaRepayOrderMapperExt kaolaRepayOrderMapperExt;

    @Autowired
    private KaolaWithholdOrderMapperExt kaolaWithholdOrderMapperExt;


    /**
     * 考拉理财正常还款回调
     *
     * @param kaolaRepayOrder
     * @param kaolaWithholdOrder
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public Result nomalRepayCallback(KaolaRepayOrder kaolaRepayOrder, KaolaWithholdOrder kaolaWithholdOrder) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = kaolaRepayOrder.getProjectId();// 项目ID
        Integer period = kaolaRepayOrder.getRepayNo();// 还款期数

        // 查询项目表信息
        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);

        // 查询你我金融还款计划 (0=待还款，1=已经正常还款，2=逾期，3=坏账)
        ProjectBorrowerPlanNew projectBorrowerPlan = projectBorrowerPlanNewMapperExt.selectByProjectAndPeriod(projectId, period);
        if (projectBorrowerPlan == null) {
            log.info("考拉理财还款回调--未查询到你我金融对应的还款计划!projectId：{},period:{}", projectId, period);
            result.setMessage("未查询到你我金融对应的还款计划!");
            return result;
        }
        // 已正常还款
        if (!projectBorrowerPlan.getStatus().equals(BorrowerPlanRefundStatusEnum.NON_REPAYMENT.getCode())) {
            log.info("考拉理财还款回调--当前还款计划已结清!projectId：{},period:{}", projectId, period);
            result.setMessage("当前还款计划已结清!");
            return result;
        }

        // 已结清
        if (RepayStatusEnum.SETTLEMENT.getCode().equals(summary.getRepayStatus())) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }

        ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO = projectBorrowerPlanNewMapperExt.selectByProjectIdAndPeroidForAmount(summary.getProjectId(), projectBorrowerPlan.getPeriod());

        this.handRefundByPeriod(kaolaRepayOrder, summary, projectBorrowerAmountSumDTO, kaolaWithholdOrder);

        //还款红包返现-借款返现红包
        activityLocalService.useLoancashBackPrize(projectId, null);
        //正常还款useSceneEnum可以为空，提前还款必传
        activityLocalService.useInterestDiscountPrize(projectId, period, null);

        result.setRet(Result.SUCCESS_RET);
        updateKaolaRepayOrderSuccess(kaolaRepayOrder, kaolaWithholdOrder);
        return result;
    }


    /**
     * 考拉理财逾期还款回调(目前只支持还当前期)
     *
     * @param kaolaRepayOrder
     * @param kaolaWithholdOrder
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public Result overDueCallback(KaolaRepayOrder kaolaRepayOrder, KaolaWithholdOrder kaolaWithholdOrder) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = kaolaRepayOrder.getProjectId();// 项目ID
        Integer period = kaolaRepayOrder.getRepayNo();// 还款期数

        // 查询项目表信息
        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);

        // 查询你我金融还款计划 (0=待还款，1=已经正常还款，2=逾期，3=坏账)
        ProjectBorrowerPlanNew projectBorrowerPlan = projectBorrowerPlanNewMapperExt.selectByProjectAndPeriod(projectId, period);
        if (projectBorrowerPlan == null) {
            log.info("考拉理财还款回调--未查询到你我金融对应的还款计划!projectId：{},period:{}", projectId, period);
            result.setMessage("未查询到你我金融对应的还款计划!");
            return result;
        }
        // 已正常还款
        if (!projectBorrowerPlan.getStatus().equals(BorrowerPlanRefundStatusEnum.NON_REPAYMENT.getCode())) {
            log.info("考拉理财还款回调--当前还款计划已结清!projectId：{},period:{}", projectId, period);
            result.setMessage("当前还款计划已结清!");
            return result;
        }
        // 已结清
        if (RepayStatusEnum.SETTLEMENT.getCode().equals(summary.getRepayStatus())) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }

        ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO = projectBorrowerPlanNewMapperExt.selectByProjectIdAndPeroidForAmount(summary.getProjectId(), projectBorrowerPlan.getPeriod());

        //本息相等，全额还款
        this.handlePlanAndCredit(summary, projectBorrowerAmountSumDTO);

        //本期还完
        this.handOnePeriodRepay(summary, RepayStatusEnum.OVERDUE);

        // 还款流水
        recordSinglePeriodFunddetailForOverDue(kaolaRepayOrder, summary, projectBorrowerAmountSumDTO, kaolaWithholdOrder);

        result.setRet(Result.SUCCESS_RET);
        updateKaolaRepayOrderSuccess(kaolaRepayOrder, kaolaWithholdOrder);
        return result;
    }


    /**
     * 考拉理财提前结清还款回调
     *
     * @param kaolaRepayOrder
     * @param kaolaWithholdOrder
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public Result settleRepayCallback(KaolaRepayOrder kaolaRepayOrder, KaolaWithholdOrder kaolaWithholdOrder) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = null;// 项目ID
        projectId = kaolaRepayOrder.getProjectId();// 项目ID

        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);
        // 已经提前结清
        if (RepayStatusEnum.SETTLEMENT.getCode().equals(summary.getRepayStatus())) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }
        Project project = projectMapperExt.selectByPrimaryKey(projectId);
        log.info("考拉还款回调--提前结清回调处理开始,标的号{}", summary.getProjectId());
        this.handleOverDebt(kaolaRepayOrder, project, summary, kaolaWithholdOrder);
        //还款红包返现-借款返现红包
        activityLocalService.useLoancashBackPrize(summary.getProjectId(), UserPrizeUseSceneEnum.REPAYMENT_ADVANCE);
        //还款红包返现-借款利率折扣卡
        activityLocalService.useInterestDiscountPrize(summary.getProjectId(), summary.getCurrentPeriod(), UserPrizeUseSceneEnum.REPAYMENT_ADVANCE);

        result.setRet(Result.SUCCESS_RET);
        updateKaolaRepayOrderSuccess(kaolaRepayOrder, kaolaWithholdOrder);
        return result;
    }


    /**
     * 考拉理财严重逾期还款（全部还完）
     *
     * @param kaolaRepayOrder
     * @param kaolaWithholdOrder
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public Result settleBadDebtDue(KaolaRepayOrder kaolaRepayOrder, KaolaWithholdOrder kaolaWithholdOrder) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = kaolaRepayOrder.getProjectId();// 项目ID

        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);
        // 已结清
        if (RepayStatusEnum.SETTLEMENT.getCode().equals(summary.getRepayStatus())) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }
        Project project = projectMapperExt.selectByPrimaryKey(projectId);
        log.info("考拉还款回调--严重逾期还款（全部还完）回调处理开始,标的号{}", summary.getProjectId());

        //2 结清（第二次将坏账那期之后的所有结清）
        handleBadDebtRepay(kaolaRepayOrder, kaolaWithholdOrder, project, summary);
        result.setRet(Result.SUCCESS_RET);
        updateKaolaRepayOrderSuccess(kaolaRepayOrder, kaolaWithholdOrder);
        return result;
    }


    /**
     * （给正常还款和逾期还款使用）修改ProjectBorrowerPlan的状态（还款状态、结清时间）
     * 和ProjectBorrowerSummary的状态（当前期数、还款状态、应还款日期、自动还款日期）
     *
     * @param summary
     */
    private void handOnePeriodRepay(ProjectBorrowerSummary summary, RepayStatusEnum repayStatusEnumForSummary) {

        //1、还款计划表状态，2、summary期数+1 3、标的状态（最后一期，结清债权）
        ProjectBorrowerPlanNew projectBorrowerPlanNew = projectBorrowerPlanNewMapperExt.selectByProjectAndPeriod(summary.getProjectId(), summary.getCurrentPeriod());
        ProjectBorrowerPlanNew projectBorrowerPlanNewForUpdate = new ProjectBorrowerPlanNew();
        projectBorrowerPlanNewForUpdate.setId(projectBorrowerPlanNew.getId());
        Byte refundStatusForPlan = repayStatusEnumForSummary == RepayStatusEnum.NORMAL ? BorrowerPlanRefundStatusEnum.NORMAL_REPAYMENT.getCode() : BorrowerPlanRefundStatusEnum.OVERDUE_REPAYMENT.getCode();
        projectBorrowerPlanNewForUpdate.setStatus(refundStatusForPlan);
        //罚息清零
//        projectBorrowerPlanNewForUpdate.setPenaltyFee(BigDecimal.ZERO);
        projectBorrowerPlanNewForUpdate.setOverDate(commonLocalService.getKaolaCurrentDate());
        projectBorrowerPlanNewForUpdate.setUpdateTime(new Date());
        projectBorrowerPlanNewMapperExt.updateByPrimaryKeySelective(projectBorrowerPlanNewForUpdate);

        ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO = projectBorrowerPlanNewMapperExt.selectByProjectIdAndPeroidForAmount(summary.getProjectId(), projectBorrowerPlanNew.getPeriod());

        //当期已还
        if (projectBorrowerAmountSumDTO.getRefundedCapital().add(projectBorrowerAmountSumDTO.getRefundedInterest()).
                equals(projectBorrowerAmountSumDTO.getCapital().add(projectBorrowerAmountSumDTO.getInterest()))) {
            if (summary.getCurrentPeriod().equals(summary.getTotalPeriod())) {
                //最后一期
                ProjectBorrowerSummary summaryUpdater = new ProjectBorrowerSummary();
                summaryUpdater.setProjectId(summary.getProjectId());
                //还款状态
                summaryUpdater.setRepayStatus(RepayStatusEnum.SETTLEMENT.getCode());
                summaryUpdater.setOverTime(new Date());
                projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryUpdater);
                Integer nums = projectBorrowerPlanNewMapperExt.countOverdueNums(summary.getBorrowerUserId(), summary.getProjectId());
                RepayStatusEnum repayStatusEnum = nums > 0 ? RepayStatusEnum.OVERDUE : RepayStatusEnum.NORMAL;
                this.updateProjectStatusForFinish(repayStatusEnum, summary, projectBorrowerAmountSumDTO);

            } else if (summary.getCurrentPeriod().intValue() < summary.getTotalPeriod()) {
                ProjectBorrowerPlanNew projectBorrowerPlanForNext = projectBorrowerPlanNewMapperExt.selectByProjectAndPeriod(summary.getProjectId(), summary.getCurrentPeriod() + 1);
                //非最后一期，正常还款
                ProjectBorrowerSummary summaryUpdater = new ProjectBorrowerSummary();
                summaryUpdater.setPreviousRefundDate(summary.getRefundDate());
                summaryUpdater.setProjectId(summary.getProjectId());
                //当前期数
                summaryUpdater.setCurrentPeriod(summary.getCurrentPeriod() + 1);
                //还款状态
                summaryUpdater.setRepayStatus(RepayStatusEnum.NORMAL.getCode());
                //应还款日期
                summaryUpdater.setRefundDate(projectBorrowerPlanForNext.getRefundDate());
                //自动还款日期
                summaryUpdater.setAutoRefundDate(projectBorrowerPlanForNext.getRefundDate());
                projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryUpdater);
                this.updateProjectStatusForRepaying(repayStatusEnumForSummary, summary, projectBorrowerAmountSumDTO);

            }
        } else {
            log.error("handOnePeriodRepay error.");
        }
    }

    /**
     * (给提前结清还款用)提前结清
     *
     * @param project
     * @param summary
     */
    private void handleOverDebt(KaolaRepayOrder kaolaRepayOrder, Project project, ProjectBorrowerSummary summary, KaolaWithholdOrder kaolaWithholdOrder) {
        List<ProjectBorrowerPlanNew> projectBorrowerPlanList = projectBorrowerPlanNewMapperExt.selectNeedRefundList(summary.getProjectId(), null);

        List<ProjectBorrowerPlanNewDTO> projectBorrowerPlanNewDTOS = new ArrayList<>();

        //已还总本金
        BigDecimal refundedCorpus = BigDecimal.ZERO;
        //已还总利息
        BigDecimal refundedInterest = BigDecimal.ZERO;
        //已还罚息
        BigDecimal refundedPenaltyFeeForSummary = BigDecimal.ZERO;
        for (ProjectBorrowerPlanNew projectBorrowerPlan : projectBorrowerPlanList) {
            ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO = projectBorrowerPlanNewMapperExt.selectByProjectIdAndPeroidForAmount(summary.getProjectId(), projectBorrowerPlan.getPeriod());
            projectBorrowerPlanNewDTOS.add(projectBorrowerAmountSumDTO);
            if (projectBorrowerPlan.getPeriod().equals(summary.getCurrentPeriod())) {

                //修改已还罚息(原来的已还罚息+待还罚息)
                updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.PENALTY, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getPenaltyFee());
                //修改已还利息
                if (projectBorrowerPlan.getRefundDate().before(new DateTime(commonLocalService.getKaolaCurrentDate()).plusMonths(1).minusDays(1).toDate())) {
                    updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.INTEREST, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getInterest());
                }
                refundedInterest = refundedInterest.add(projectBorrowerAmountSumDTO.getInterest().subtract(projectBorrowerAmountSumDTO.getRefundedInterest()));
                //已还罚息
                refundedPenaltyFeeForSummary = refundedPenaltyFeeForSummary.add(projectBorrowerAmountSumDTO.getPenaltyFee().subtract(projectBorrowerAmountSumDTO.getRefundedPenaltyFee()));
            }
            //修改已还本金
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.CAPITAL, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getCapital());
//            borrowerPlanUpdater.setRefundedCapital(projectBorrowerPlan.getCapital());
            //修改平台管理费
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.MANAGEMENT_FEE, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getManagementFee());
//            borrowerPlanUpdater.setRefundedManagementFee(projectBorrowerPlan.getManagementFee());
            //修改已还担保服务费
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.GUARANTEE_FEE, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getGuaranteeFee());
//            borrowerPlanUpdater.setRefundedGuaranteeFee(projectBorrowerPlan.getGuaranteeFee());
            //还款状态
            ProjectBorrowerPlanNew borrowerPlanUpdater = new ProjectBorrowerPlanNew();
            borrowerPlanUpdater.setId(projectBorrowerPlan.getId());
            borrowerPlanUpdater.setStatus(BorrowerPlanRefundStatusEnum.OVER_DEBT_REPAYMENT.getCode());
            borrowerPlanUpdater.setOverDate(commonLocalService.getKaolaCurrentDate());
            borrowerPlanUpdater.setUpdateTime(new Date());
            //改查询方法为累加数据修改
            projectBorrowerPlanNewMapperExt.updateByPrimaryKeySelective(borrowerPlanUpdater);
            refundedCorpus = refundedCorpus.add(projectBorrowerAmountSumDTO.getCapital());
        }


        //考拉的标没有债权关系，也没有投资人相关修改（投资人在考拉端）
        ProjectBorrowerSummary summaryForUpdate = new ProjectBorrowerSummary();
        //已还总本金(累加)
        summaryForUpdate.setRefundedCorpus(summary.getRefundedCorpus().add(refundedCorpus));
        //已还总利息(累加)
        summaryForUpdate.setRefundedInterest(summary.getRefundedInterest().add(refundedInterest));
        //已还平台管理费(设置为平台管理费)
        summaryForUpdate.setRefundedManagementFee(project.getManageFee());
        //已还担保服务费(设置为担保服务费)
        summaryForUpdate.setRefundedGuaranteeFee(project.getGuaranteeFee());
        //已还罚息
        summaryForUpdate.setRefundedPenaltyFee(summary.getRefundedPenaltyFee().add(refundedPenaltyFeeForSummary));
        summaryForUpdate.setRepayStatus(RepayStatusEnum.SETTLEMENT.getCode());
        summaryForUpdate.setProjectId(project.getProjectId());
        summaryForUpdate.setBorrowerUserId(summary.getBorrowerUserId());
        summaryForUpdate.setOverTime(new Date());
        //该查询方法为累加数据修改
        projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryForUpdate);

        this.updateProjectStatusForFinish(RepayStatusEnum.SETTLEMENT, summary, null);

        // 添加流水
        recordSettleRepaymentFunddetail(kaolaRepayOrder, summary, projectBorrowerPlanNewDTOS, kaolaWithholdOrder);
    }

    /**
     * （给正常还款使用）
     *
     * @param summary
     * @param kaolaRepayOrder
     * @param projectBorrowerAmountSumDTO
     */
    protected void handRefundByPeriod(KaolaRepayOrder kaolaRepayOrder, ProjectBorrowerSummary summary, ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO, KaolaWithholdOrder kaolaWithholdOrder) {

        //本息相等，全额还款
        this.handlePlanAndCredit(summary, projectBorrowerAmountSumDTO);

        //本期还完
        this.handOnePeriodRepay(summary, RepayStatusEnum.NORMAL);

        // 还款流水
        recordSingePeriodFunddetail(kaolaRepayOrder, summary, projectBorrowerAmountSumDTO, kaolaWithholdOrder);
    }


    /**
     * （给正常还款和逾期还款使用）修改ProjectBorrowerSummary的费用相关数值（已还总本金、已还总利息、已还平台管理费、已还罚息、已还担保服务费）
     * 和ProjectBorrowerPlan的相关费用（已还总本金、已还总利息、已还平台管理费、已还罚息、已还担保服务费）
     *
     * @param summary
     * @param projectBorrowerAmountSumDTO
     */
    protected void handlePlanAndCredit(ProjectBorrowerSummary summary, ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO) {


        ProjectBorrowerSummary summaryUpdater = new ProjectBorrowerSummary();
        //剩余应还本金
        BigDecimal shouldRefundCapital = projectBorrowerAmountSumDTO.getCapital().subtract(projectBorrowerAmountSumDTO.getRefundedCapital());
        //剩余应还利息
        BigDecimal shouldRefundInterest = projectBorrowerAmountSumDTO.getInterest().subtract(projectBorrowerAmountSumDTO.getRefundedInterest());
        //剩余应还平台管理费
        BigDecimal shouldRefundManagementFee = projectBorrowerAmountSumDTO.getManagementFee().subtract(projectBorrowerAmountSumDTO.getRefundedManagementFee());
        //剩余应还担保服务费
        BigDecimal shouldRefundGuaranteeFee = projectBorrowerAmountSumDTO.getGuaranteeFee().subtract(projectBorrowerAmountSumDTO.getRefundedGuaranteeFee());
        //剩余应还罚息
        BigDecimal shouldRefundPenaltyFee = projectBorrowerAmountSumDTO.getPenaltyFee().subtract(projectBorrowerAmountSumDTO.getRefundedPenaltyFee());

        // refunded_corpus已还总本金(累加)
        summaryUpdater.setRefundedCorpus(summary.getRefundedCorpus().add(shouldRefundCapital));
        // refunded_interest 已还总利息(累加)
        summaryUpdater.setRefundedInterest(summary.getRefundedInterest().add(shouldRefundInterest));
        // refunded_management_fee 已还平台管理费(累加)
        summaryUpdater.setRefundedManagementFee(summary.getRefundedManagementFee().add(shouldRefundManagementFee));
        // refunded_penalty_fee 已还罚息(累加)
        summaryUpdater.setRefundedPenaltyFee(summary.getRefundedPenaltyFee().add(shouldRefundPenaltyFee));
        //  `refunded_guarantee_fee` 已还担保服务费(累加)
        summaryUpdater.setRefundedGuaranteeFee(summary.getRefundedGuaranteeFee().add(shouldRefundGuaranteeFee));
        summaryUpdater.setProjectId(summary.getProjectId());

        summaryUpdater.setBorrowerUserId(summary.getBorrowerUserId());
        projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryUpdater);

        //修改已还本金
        updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.CAPITAL, projectBorrowerAmountSumDTO.getId(), projectBorrowerAmountSumDTO.getCapital());
        //修改已还利息
        updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.INTEREST, projectBorrowerAmountSumDTO.getId(), projectBorrowerAmountSumDTO.getInterest());
        //修改已还罚息
        updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.PENALTY, projectBorrowerAmountSumDTO.getId(), projectBorrowerAmountSumDTO.getPenaltyFee());
        //修改已还平台管理费
        updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.MANAGEMENT_FEE, projectBorrowerAmountSumDTO.getId(), projectBorrowerAmountSumDTO.getManagementFee());
        //修改已还担保服务费
        updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.GUARANTEE_FEE, projectBorrowerAmountSumDTO.getId(), projectBorrowerAmountSumDTO.getGuaranteeFee());


    }


    private void handleBadDebtRepay(KaolaRepayOrder kaolaRepayOrder, KaolaWithholdOrder kaolaWithholdOrder, Project project, ProjectBorrowerSummary summary) {
        List<ProjectBorrowerPlanNew> projectBorrowerPlanNewList = projectBorrowerPlanNewMapperExt.selectNeedRefundList(summary.getProjectId(), null);
        //已还总本金
        BigDecimal refundedCorpusForSummary = BigDecimal.ZERO;
        //已还总利息
        BigDecimal refundedInterestForSummary = BigDecimal.ZERO;
        //已还罚息
        BigDecimal refundedPenaltyFeeForSummary = BigDecimal.ZERO;
        List<ProjectBorrowerPlanNewDTO> projectBorrowerPlanNewDTOS = new ArrayList<>();

        for (ProjectBorrowerPlanNew projectBorrowerPlan : projectBorrowerPlanNewList) {
            ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO = projectBorrowerPlanNewMapperExt.selectByProjectIdAndPeroidForAmount(summary.getProjectId(), projectBorrowerPlan.getPeriod());
            projectBorrowerPlanNewDTOS.add(projectBorrowerAmountSumDTO);

            //已还罚息
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.PENALTY, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getPenaltyFee());
//            borrowerPlanUpdater.setRefundedPenaltyFee(projectBorrowerPlan.getRefundedPenaltyFee().add(projectBorrowerPlan.getPenaltyFee()));

            // 严重逾期需要还两期利息
            if (projectBorrowerPlan.getPeriod().equals(summary.getCurrentPeriod()) || projectBorrowerPlan.getPeriod().equals(summary.getCurrentPeriod() + 1)) {
                BigDecimal needPayInterest = projectBorrowerAmountSumDTO.getInterest().subtract(projectBorrowerAmountSumDTO.getRefundedInterest());// 应还利息
                //已还利息
                updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.INTEREST, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getInterest());
//                borrowerPlanUpdater.setRefundedInterest(projectBorrowerPlan.getInterest());
                refundedInterestForSummary = refundedInterestForSummary.add(needPayInterest);
            }
            //summary已还罚息（所有的待还罚息）
            refundedPenaltyFeeForSummary = refundedPenaltyFeeForSummary.add(projectBorrowerAmountSumDTO.getPenaltyFee().subtract(projectBorrowerAmountSumDTO.getRefundedPenaltyFee()));
            ProjectBorrowerPlanNew borrowerPlanUpdater = new ProjectBorrowerPlanNew();
            borrowerPlanUpdater.setId(projectBorrowerPlan.getId());
            //还款状态
            borrowerPlanUpdater.setStatus(BorrowerPlanRefundStatusEnum.OVERDUE_REPAYMENT.getCode());
            borrowerPlanUpdater.setOverDate(commonLocalService.getKaolaCurrentDate());
            borrowerPlanUpdater.setUpdateTime(new Date());
            //改查询方法为累加数据修改
            projectBorrowerPlanNewMapperExt.updateByPrimaryKeySelective(borrowerPlanUpdater);

            //修改已还本金
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.CAPITAL, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getCapital());
//            borrowerPlanUpdater.setRefundedCapital(projectBorrowerPlan.getCapital());
            //修改平台管理费
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.MANAGEMENT_FEE, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getManagementFee());
//            borrowerPlanUpdater.setRefundedManagementFee(projectBorrowerPlan.getManagementFee());
            //修改已还担保服务费
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.GUARANTEE_FEE, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getGuaranteeFee());
//            borrowerPlanUpdater.setRefundedGuaranteeFee(projectBorrowerPlan.getGuaranteeFee());
            //罚息清零
            updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum.PENALTY, projectBorrowerPlan.getId(), projectBorrowerAmountSumDTO.getPenaltyFee());
//            borrowerPlanUpdater.setPenaltyFee(BigDecimal.ZERO);
            refundedCorpusForSummary = refundedCorpusForSummary.add(projectBorrowerAmountSumDTO.getCapital().subtract(projectBorrowerAmountSumDTO.getRefundedCapital()));
        }


        //考拉的标没有债权关系，也没有投资人相关修改（投资人在考拉端）
        ProjectBorrowerSummary summaryForUpdate = new ProjectBorrowerSummary();
        //已还总本金(累加)
        summaryForUpdate.setRefundedCorpus(summary.getRefundedCorpus().add(refundedCorpusForSummary));
        //已还总利息(累加)
        summaryForUpdate.setRefundedInterest(summary.getRefundedInterest().add(refundedInterestForSummary));
        //已还平台管理费(设置为平台管理费)
        summaryForUpdate.setRefundedManagementFee(project.getManageFee());
        //已还担保服务费(设置为担保服务费)
        summaryForUpdate.setRefundedGuaranteeFee(project.getGuaranteeFee());
        //已还罚息
        summaryForUpdate.setRefundedPenaltyFee(summary.getRefundedPenaltyFee().add(refundedPenaltyFeeForSummary));
        summaryForUpdate.setProjectId(project.getProjectId());
        summaryForUpdate.setBorrowerUserId(summary.getBorrowerUserId());
        summaryForUpdate.setRepayStatus(RepayStatusEnum.SETTLEMENT.getCode());
        summaryForUpdate.setOverTime(new Date());
        //该查询方法为累加数据修改
        projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryForUpdate);

        this.updateProjectStatusForFinish(RepayStatusEnum.BADLOANS, summary, null);

        // 添加流水
        recordBadDebtFunddetail(kaolaRepayOrder, kaolaWithholdOrder, summary, projectBorrowerPlanNewDTOS);
    }


    /********记录流水**********/

    /**
     * 记录还款一期账单流水（给逾期还款使用）
     *
     * @param kaolaRepayOrder
     * @param summary
     * @param projectBorrowerAmountSumDTO
     * @param kaolaWithholdOrder
     */
    private void recordSinglePeriodFunddetailForOverDue(KaolaRepayOrder kaolaRepayOrder, ProjectBorrowerSummary summary, ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO, KaolaWithholdOrder kaolaWithholdOrder) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);
        Long projectId = kaolaRepayOrder.getProjectId();// 项目ID
        Integer period = kaolaRepayOrder.getRepayNo();// 还款期数
        BigDecimal rechargeAmount = kaolaRepayOrder.getRepayAmount();
        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                rechargeAmount, InoutTypeEnum.IN_TYPE, null, null);
        // 充值流水(用户)--充值金额
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, rechargeAmount, BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        // 还款(用户):本金+利息+平台管理费+担保服务费
        AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
        BigDecimal needPayCapital = projectBorrowerAmountSumDTO.getCapital().subtract(projectBorrowerAmountSumDTO.getRefundedCapital());// 应还本金
        BigDecimal needPayInterest = projectBorrowerAmountSumDTO.getInterest().subtract(projectBorrowerAmountSumDTO.getRefundedInterest());// 应还利息
        BigDecimal needPayManageFee = projectBorrowerAmountSumDTO.getManagementFee().subtract(projectBorrowerAmountSumDTO.getRefundedManagementFee());// 应还平台管理费
        BigDecimal needPayGuaranteeFee = projectBorrowerAmountSumDTO.getGuaranteeFee().subtract(projectBorrowerAmountSumDTO.getRefundedGuaranteeFee());// 应还担保服务费
        BigDecimal needPayPenalyFee = projectBorrowerAmountSumDTO.getPenaltyFee().subtract(projectBorrowerAmountSumDTO.getRefundedPenaltyFee());// 应还罚息
        BigDecimal repaymentAmount = needPayCapital.add(needPayInterest).add(needPayManageFee).add(needPayGuaranteeFee).add(needPayPenalyFee);
        KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                repaymentAmount, InoutTypeEnum.OUT_TYPE, projectId, null);
        // 还款(用户)-本金
        if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
        }
        // 还款(用户)-利息
        if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);
        }
        // 还款(用户)-平台管理费
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
        }
        // 还款(用户)-担保服务费
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
        }
        // 还款(用户)-罚息
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill penalyFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayPenalyFee, BillSecondSubjectEnum.USER_REPAYMENT_PENALTY, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, penalyFeeBillDetail);
        }
        if (repaymentRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentRequestDTO);
        }

        // 回款(平台)：平台管理费
        AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, kaolaWithholdOrder.getReqNo(),
                projectBorrowerAmountSumDTO.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerAmountSumDTO.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, period);
            addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
        }
        if (repaymentForPlatRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentForPlatRequestDTO);
        }

        // 回款(担保公司)：担保服务费+罚息
        AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, kaolaWithholdOrder.getReqNo(),
                projectBorrowerAmountSumDTO.getGuaranteeFee().add(needPayPenalyFee), InoutTypeEnum.IN_TYPE, projectId, null);
        //担保服务费【借】
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
        }
        //回款(担保公司)-垫付罚息回款【借】
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranTeePenalyFeeBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayPenalyFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranTeePenalyFeeBillDetail);
        }

        //回款(担保公司)-垫付本金回款【借】
        if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill advanceCapitalBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayCapital, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceCapitalBackBillDetail);
        }

        //回款(担保公司)-垫付利息回款【借】
        if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill advanceInterestBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayInterest, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceInterestBackBillDetail);
        }


        if (guaranteeFeeRequestDTO.getUserId() != null) {
            requestDTOList.add(guaranteeFeeRequestDTO);
        }

        niiwooBillDubboService.addThirdBills(requestDTOList);
    }


    /**
     * 记录还款一期账单流水（给正常还款使用）
     *
     * @param kaolaRepayOrder
     * @param summary
     * @param projectBorrowerAmountSumDTO
     * @param kaolaWithholdOrder
     */
    private void recordSingePeriodFunddetail(KaolaRepayOrder kaolaRepayOrder, ProjectBorrowerSummary summary, ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO, KaolaWithholdOrder kaolaWithholdOrder) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);

        Long projectId = kaolaRepayOrder.getProjectId();// 项目ID
        Integer period = kaolaRepayOrder.getRepayNo();// 还款期数
        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                kaolaRepayOrder.getRepayAmount(), InoutTypeEnum.IN_TYPE, null, null);
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, kaolaRepayOrder.getRepayAmount(), BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        // 还款(用户):本金+利息+平台管理费+担保服务费
        AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
        BigDecimal needPayCapital = projectBorrowerAmountSumDTO.getCapital().subtract(projectBorrowerAmountSumDTO.getRefundedCapital());// 应还本金
        BigDecimal needPayInterest = projectBorrowerAmountSumDTO.getInterest().subtract(projectBorrowerAmountSumDTO.getRefundedInterest());// 应还利息
        BigDecimal needPayManageFee = projectBorrowerAmountSumDTO.getManagementFee().subtract(projectBorrowerAmountSumDTO.getRefundedManagementFee());// 应还平台管理费
        BigDecimal needPayGuaranteeFee = projectBorrowerAmountSumDTO.getGuaranteeFee().subtract(projectBorrowerAmountSumDTO.getRefundedGuaranteeFee());// 应还担保服务费
        BigDecimal needPayPenalyFee = projectBorrowerAmountSumDTO.getPenaltyFee().subtract(projectBorrowerAmountSumDTO.getRefundedPenaltyFee());// 应还罚息
        BigDecimal repaymentAmount = needPayCapital.add(needPayInterest).add(needPayManageFee).add(needPayGuaranteeFee).add(needPayPenalyFee);
        KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                repaymentAmount, InoutTypeEnum.OUT_TYPE, projectId, null);
        // 还款(用户)-本金
        if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
        }
        // 还款(用户)-利息
        if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);
        }
        // 还款(用户)-平台管理费
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
        }
        // 还款(用户)-担保服务费
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
        }
        // 还款(用户)-罚息
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill penalyFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayPenalyFee, BillSecondSubjectEnum.USER_REPAYMENT_PENALTY, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, penalyFeeBillDetail);
        }
        if (repaymentRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentRequestDTO);
        }

        // 回款(平台)：平台管理费
        AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, kaolaWithholdOrder.getReqNo(),
                projectBorrowerAmountSumDTO.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerAmountSumDTO.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, period);
            addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
        }
        if (repaymentForPlatRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentForPlatRequestDTO);
        }

        // 回款(担保公司)：担保服务费+罚息
        AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, kaolaWithholdOrder.getReqNo(),
                projectBorrowerAmountSumDTO.getGuaranteeFee().add(needPayPenalyFee), InoutTypeEnum.IN_TYPE, projectId, null);
        //回款(担保公司)-担保服务费【借】
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
        }
        //回款(担保公司)-垫付罚息【借】
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranTeePenalyFeeBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayPenalyFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranTeePenalyFeeBillDetail);
        }
        //回款(担保公司)-垫付本金回款【借】
        if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill advanceCapitalBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayCapital, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceCapitalBackBillDetail);
        }

        //回款(担保公司)-垫付利息回款【借】
        if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill advanceInterestBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayInterest, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceInterestBackBillDetail);
        }


        if (guaranteeFeeRequestDTO.getUserId() != null) {
            requestDTOList.add(guaranteeFeeRequestDTO);
        }

        niiwooBillDubboService.addThirdBills(requestDTOList);
    }

    /**
     * 记录提前结清流水
     *
     * @param kaolaRepayOrder
     * @param summary
     * @param projectBorrowerPlanNewDTOS
     * @param kaolaWithholdOrder
     */
    private void recordSettleRepaymentFunddetail(KaolaRepayOrder kaolaRepayOrder, ProjectBorrowerSummary summary, List<ProjectBorrowerPlanNewDTO> projectBorrowerPlanNewDTOS, KaolaWithholdOrder kaolaWithholdOrder) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);
        // 项目ID
        Long projectId = kaolaRepayOrder.getProjectId();

        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                kaolaRepayOrder.getRepayAmount(), InoutTypeEnum.IN_TYPE, null, null);
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, kaolaRepayOrder.getRepayAmount(), BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        for (ProjectBorrowerPlanNewDTO projectBorrowerPlan : projectBorrowerPlanNewDTOS) {
            // 还款(用户):本金+利息+平台管理费+担保服务费
            AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                    kaolaRepayOrder.getRepayAmount(), InoutTypeEnum.OUT_TYPE, projectId, null);

            // 还款(用户)-本金
            BigDecimal needPayCapital = projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital());// 应还本金
            if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, projectBorrowerPlan.getPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
            }

            // 还款(用户)-平台管理费
            BigDecimal needPayManageFee = projectBorrowerPlan.getManagementFee().subtract(projectBorrowerPlan.getRefundedManagementFee());// 应还平台管理费
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, projectBorrowerPlan.getPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
            }

            // 还款(用户)-担保服务费
            BigDecimal needPayGuaranteeFee = projectBorrowerPlan.getGuaranteeFee().subtract(projectBorrowerPlan.getRefundedGuaranteeFee());// 应还担保服务费
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, projectBorrowerPlan.getPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
            }
            if (repaymentRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentRequestDTO);
            }

            // 回款(平台)：平台管理费
            AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, kaolaWithholdOrder.getReqNo(),
                    projectBorrowerPlan.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerPlan.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, projectBorrowerPlan.getPeriod());
                addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
            }
            if (repaymentForPlatRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentForPlatRequestDTO);
            }

            // 回款(担保公司)：担保服务费
            AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, kaolaWithholdOrder.getReqNo(),
                    projectBorrowerPlan.getGuaranteeFee(), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                //回款(担保公司)-担保服务费【借】
                KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, projectBorrowerPlan.getPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
            }
            //回款(担保公司)-垫付本金回款【借】
            if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill advanceCapitalBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayCapital, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL, projectBorrowerPlan.getPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceCapitalBackBillDetail);
            }

            if (projectBorrowerPlan.getPeriod().equals(summary.getCurrentPeriod())
                    && projectBorrowerPlan.getRefundDate().before(new DateTime(commonLocalService.getKaolaCurrentDate()).plusMonths(1).minusDays(1).toDate())) {
                // 应还利息
                BigDecimal needPayInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());
                if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
                    // 还款(用户)--还款利息
                    KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, projectBorrowerPlan.getPeriod());
                    addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);

                    //回款(担保公司)-垫付利息回款【借】
                    KaolaDetailBill advanceInterestBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayInterest, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST, projectBorrowerPlan.getPeriod());
                    addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceInterestBackBillDetail);

                }
            }


            if (guaranteeFeeRequestDTO.getUserId() != null) {
                requestDTOList.add(guaranteeFeeRequestDTO);
            }
        }
        niiwooBillDubboService.addThirdBills(requestDTOList);
    }

    /**
     * 记录严重逾期还款流水
     *
     * @param kaolaRepayOrder
     * @param kaolaWithholdOrder
     * @param summary
     * @param projectBorrowerPlanNewDTOS
     */
    private void recordBadDebtFunddetail(KaolaRepayOrder kaolaRepayOrder, KaolaWithholdOrder kaolaWithholdOrder, ProjectBorrowerSummary summary, List<ProjectBorrowerPlanNewDTO> projectBorrowerPlanNewDTOS) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);
        // 项目ID
        Long projectId = kaolaRepayOrder.getProjectId();
        BigDecimal rechargeAmount = kaolaRepayOrder.getRepayAmount();

        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        //充值流水(用户)--充值金额
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                rechargeAmount, InoutTypeEnum.IN_TYPE, null, null);
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, rechargeAmount, BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        for (ProjectBorrowerPlanNewDTO projectBorrowerPlanNewDTO : projectBorrowerPlanNewDTOS) {
            // 还款(用户):本金+利息+平台管理费+担保服务费
            AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, kaolaWithholdOrder.getReqNo(),
                    kaolaRepayOrder.getRepayAmount(), InoutTypeEnum.OUT_TYPE, projectId, null);

            // 还款(用户)-本金
            BigDecimal needPayCapital = projectBorrowerPlanNewDTO.getCapital().subtract(projectBorrowerPlanNewDTO.getRefundedCapital());// 应还本金
            if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
            }

            // 还款(用户)-平台管理费
            BigDecimal needPayManageFee = projectBorrowerPlanNewDTO.getManagementFee().subtract(projectBorrowerPlanNewDTO.getRefundedManagementFee());// 应还平台管理费
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
            }

            // 还款(用户)-担保服务费
            BigDecimal needPayGuaranteeFee = projectBorrowerPlanNewDTO.getGuaranteeFee().subtract(projectBorrowerPlanNewDTO.getRefundedGuaranteeFee());// 应还担保服务费
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
            }

            // 还款(用户)-罚息
            BigDecimal needPayPenalyFee = projectBorrowerPlanNewDTO.getPenaltyFee();// 应还罚息
            if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill penalyFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayPenalyFee, BillSecondSubjectEnum.USER_REPAYMENT_PENALTY, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, penalyFeeBillDetail);
            }
            if (repaymentRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentRequestDTO);
            }

            // 回款(平台)：平台管理费
            AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, kaolaWithholdOrder.getReqNo(),
                    projectBorrowerPlanNewDTO.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                //回款(平台)-平台管理费【极速借】
                KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerPlanNewDTO.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
            }
            if (repaymentForPlatRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentForPlatRequestDTO);
            }

            // 回款(担保公司)：担保服务费
            AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, kaolaWithholdOrder.getReqNo(),
                    projectBorrowerPlanNewDTO.getGuaranteeFee().add(needPayPenalyFee), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
            }
            //回款(担保公司)-垫付罚息回款【借】
            if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranTeePenalyFeeBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayPenalyFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranTeePenalyFeeBillDetail);
            }
            //回款(担保公司)-垫付本金回款【借】
            if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill advanceCapitalBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayCapital, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL, projectBorrowerPlanNewDTO.getPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceCapitalBackBillDetail);
            }

            // 严重逾期需要还两期利息
            if (projectBorrowerPlanNewDTO.getPeriod().equals(summary.getCurrentPeriod()) || projectBorrowerPlanNewDTO.getPeriod().equals(summary.getCurrentPeriod() + 1)) {
                BigDecimal needPayInterest = projectBorrowerPlanNewDTO.getInterest().subtract(projectBorrowerPlanNewDTO.getRefundedInterest());// 应还利息
                if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
                    // 还款(用户)--还款利息
                    KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, projectBorrowerPlanNewDTO.getPeriod());
                    addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);

                    // 回款(担保公司)---垫付利息回款【借】
                    KaolaDetailBill advanceInterestBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayInterest, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST, projectBorrowerPlanNewDTO.getPeriod());
                    addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceInterestBackBillDetail);
                }
            }

            if (guaranteeFeeRequestDTO.getUserId() != null) {
                requestDTOList.add(guaranteeFeeRequestDTO);
            }

        }
        niiwooBillDubboService.addThirdBills(requestDTOList);
    }


    /**
     * 修改Project的状态，插入项目操作记录
     *
     * @param repayStatusEnum
     * @param summary
     * @param projectBorrowerPlanNewDTO
     */
    protected void updateProjectStatusForFinish(RepayStatusEnum repayStatusEnum, ProjectBorrowerSummary summary, ProjectBorrowerPlanNewDTO projectBorrowerPlanNewDTO) {
        Project projectUpdate = new Project();
        projectUpdate.setProjectId(summary.getProjectId());
        try {
            userCreditDubboService.changeCreditNeedUpdate(summary.getBorrowerUserId(), CreditEnum.CreditAmountType.SPEED_BORROW);
        } catch (Exception e) {
            log.error("userCreditDubboService.changeCreditNeedUpdate() error", e);
        }
        switch (repayStatusEnum) {
            //正常结清
            case NORMAL:
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_NORMAL.getSubStatus());
                this.addProjectRecord(summary, projectBorrowerPlanNewDTO, ProjectDynamicEnum.FINISH_NORMAL, false);
                break;
            //逾期还款结清
            case OVERDUE:
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_OVERDUE.getSubStatus());
                this.addProjectRecord(summary, projectBorrowerPlanNewDTO, ProjectDynamicEnum.FINISH_OVERDUE, false);
                break;
            //坏账结清
            case BADLOANS:
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_BAD.getSubStatus());
                this.addProjectRecord(summary, projectBorrowerPlanNewDTO, ProjectDynamicEnum.FINISH_OVERDUE, false);
                break;
            default://提前结清
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_ADVANCE.getSubStatus());
                this.addProjectRecord(summary, projectBorrowerPlanNewDTO, ProjectDynamicEnum.FINISH_ADVANCE, false);

                break;
        }
        projectUpdate.setStatus(ProjectStatusEnum.FINISH.getStatus());
        projectMapperExt.updateByPrimaryKeySelective(projectUpdate);
    }

    /**
     * 添加项目操作动态记录.
     *
     * @param repayStatusEnum
     * @param summary
     * @param projectBorrowerAmountSumDTO
     */
    protected void updateProjectStatusForRepaying(RepayStatusEnum repayStatusEnum, ProjectBorrowerSummary summary, ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO) {
        switch (repayStatusEnum) {
            //正常还款中
            case NORMAL:
                this.addProjectRecord(summary, projectBorrowerAmountSumDTO, ProjectDynamicEnum.REPAYING_NORMAL_TEMPLATE, true);
                break;
            //逾期还款中
            case OVERDUE:
                this.addProjectRecord(summary, projectBorrowerAmountSumDTO, ProjectDynamicEnum.REPAYING_OVERDUE_TEMPLATE, true);

                Project projectUpdate = new Project();
                projectUpdate.setProjectId(summary.getProjectId());
                projectUpdate.setSubStatus(ProjectSubStatusEnum.REPAYING_INIT.getSubStatus());
                projectMapperExt.updateByPrimaryKeySelective(projectUpdate);

                break;
            //坏账还款中
            case BADLOANS:
                this.addProjectRecord(summary, projectBorrowerAmountSumDTO, ProjectDynamicEnum.REPAYING_BAD_TEMPLATE, true);
                break;
            default:
                break;
        }
    }

    /**
     * 添加项目操作动态记录
     *
     * @param summary
     * @param projectBorrowerAmountSumDTO
     * @param projectDynamicEnum
     * @param hasFeeDetail
     */
    private void addProjectRecord(ProjectBorrowerSummary summary, ProjectBorrowerPlanNewDTO projectBorrowerAmountSumDTO, ProjectDynamicEnum projectDynamicEnum, boolean hasFeeDetail) {
        ProjectDynamicDTO dto = new ProjectDynamicDTO();
        dto.setProjectId(summary.getProjectId());
        dto.setRelationId(projectBorrowerAmountSumDTO == null ? null : projectBorrowerAmountSumDTO.getProjectId());
        dto.setTradeTypeEnum(ProjectDynamicDTO.TradeTypeEnum.REPAYMENT);
        dto.setProjectDynamicEnum(projectDynamicEnum);
        dto.setUserId(summary.getBorrowerUserId());
        if (hasFeeDetail) {
            List<String> paramsList = new ArrayList<>();
            paramsList.add(projectBorrowerAmountSumDTO.getRefundedGuaranteeFee().
                    add(projectBorrowerAmountSumDTO.getRefundedManagementFee()).
                    add(projectBorrowerAmountSumDTO.getRefundedPenaltyFee()).
                    add(projectBorrowerAmountSumDTO.getRefundedInterest()).
                    add(projectBorrowerAmountSumDTO.getRefundedCapital()).toString());
            if (projectBorrowerAmountSumDTO.getRefundedGuaranteeFee().compareTo(BigDecimal.ZERO) > 0) {
                paramsList.add("担保服务费" + projectBorrowerAmountSumDTO.getRefundedGuaranteeFee());
            }
            if (projectBorrowerAmountSumDTO.getRefundedManagementFee().compareTo(BigDecimal.ZERO) > 0) {
                paramsList.add("平台管理费" + projectBorrowerAmountSumDTO.getRefundedManagementFee());
            }
            if (projectBorrowerAmountSumDTO.getRefundedInterest().compareTo(BigDecimal.ZERO) > 0) {
                paramsList.add("罚息" + projectBorrowerAmountSumDTO.getRefundedPenaltyFee());
            }
            paramsList.add("利息" + projectBorrowerAmountSumDTO.getRefundedInterest());
            paramsList.add("本金" + projectBorrowerAmountSumDTO.getRefundedCapital());
            dto.setParamsList(paramsList);
        }

        projectLocalService.addProjectDynamicRecord(dto);
    }


    /**
     * 发送还款失败消息
     *
     * @param kaolaRepayOrder
     * @param resultTradeRecord
     * @return
     * @throws Exception
     */
    public Result sendRepaymentFailMessage(KaolaRepayOrder kaolaRepayOrder, QueryTradeRecordResultDTO resultTradeRecord) throws Exception {
        Result result = new Result(Result.SUCCESS_RET);
        // 项目
        Project project = projectMapperExt.selectByPrimaryKey(kaolaRepayOrder.getProjectId());
        if (null == project) {
            log.info("未查询到你我金融对应的项目信息!projectId：{}", kaolaRepayOrder.getProjectId());
            result.setFailureMessage("未查询到你我金融对应的项目信息!");
            return result;
        }

        // 当前有效银行卡
        BankCardDTO bankCardDTO = bankCardDubboService.getUserBankCardInfo(project.getBorrowUserId());
        if (null == bankCardDTO) {
            log.info("未查询到用户有效银行卡信息!userId：{}", project.getBorrowUserId());
            result.setMessage("未查询到用户有效银行卡信息!");
            return result;
        }
        String bankAcccount = bankCardDTO.getBankAccountNo();// 银行卡账户
        // 银行卡账户是否为空
        if (StringUtils.isBlank(bankAcccount)) {
            log.info("未查询到用户有效银行卡信息!userId：{}", project.getBorrowUserId());
            result.setMessage("未查询到用户有效银行卡信息!");
            return result;
        }
        // 银行卡后四位
        String suffixBankAccount = bankAcccount.substring(bankAcccount.length() - 4,
                bankAcccount.length());

        String amount = kaolaRepayOrder.getRepayAmount().setScale(2, BigDecimal.ROUND_HALF_EVEN).toString();

        if (resultTradeRecord.getDetails().get(0).getFailureDetails() != null) {
            amount = amount + ",具体原因如下:\"" + resultTradeRecord.getDetails().get(0).getFailureDetails() + "\"";
        }

        // 项目ID，项目标题，银行卡号，欠款金额
        String[] msgParams = {project.getProjectId().toString(), suffixBankAccount, amount};
        List<Object> listForParams = Arrays.asList(msgParams);
        try {
            this.sendMsgForKaolaRepaymentFail(project.getBorrowUserId(), listForParams);
        } catch (Exception e) {
            log.error("还款回调失败发送短信sendMsgForKaolaRepaymentFail-error", e);
        }
        return result;
    }

    /**
     * @param userId
     * @param params
     * @throws Exception
     */
    public void sendMsgForKaolaRepaymentFail(String userId, List<Object> params) throws Exception {
        //发送短信
        sendSmsDubboService.sendSmsByUserId(userId, SMSTemplateKeyEnum.TEMP_KAOLALICAI_REPAYMENT_FAIL.getKey(), params);

        //发送站内信
        UserLetterRequestDTO userLetterRequestDTO = new UserLetterRequestDTO();
        userLetterRequestDTO.setToUserId(userId);
        userLetterRequestDTO.setUserLetterTypeEnum(UserLetterTypeEnum.LETTER_AND_JPUSH);

        //您好，您的借款项目【<a href="http://test.niiwoo.com:5006/h5/app/project/my_details/#/loandt?ProjectId={0}">{1}</a>】还款失败，请保证尾号{2}银行卡余额大于{3}，登录你我金融再次发起还款，如有疑问请联系钱小二。
        String hrefTemp = "<a href=\"%s\">%s</a>";
        String[] arrayForHref = new String[]{h5BorrowDetailUrl + params.get(0), params.get(0).toString()};
        String hrefContent = String.format(hrefTemp, arrayForHref);
        //站内信
        List<Object> paramsForLetter = new ArrayList<>(params);
        paramsForLetter.set(0, hrefContent);
        userLetterRequestDTO.setLetterTemplateEnum(MessageTemplateKeyEnum.LetterTemplateKeyEnum.TEMP_KAOLALICAI_REPAYMENT_FAIL);
        userLetterRequestDTO.setLetterTemplateParamList(paramsForLetter);
        //极光推送
        userLetterRequestDTO.setJpushTemplateKeyEnum(MessageTemplateKeyEnum.JPushTemplateKeyEnum.TEMP_KAOLALICAI_REPAYMENT_FAIL);
        userLetterRequestDTO.setJpushTemplateParamList(params);
        JPushExtDTO jPushExtDTO = new JPushExtDTO();
        jPushExtDTO.setRedirectPageEnum(JPushEnum.RedirectPageEnum.NOTICE_LIST_PAGE);
        userLetterRequestDTO.setJPushExt(jPushExtDTO);
        userLetterDubboService.pushLetter(userLetterRequestDTO);
    }

    /**
     * 严重逾期-第2次还款失败消息通知（站内信和短信）
     *
     * @param userId
     * @throws Exception
     */
    public void sendMsgForBadDebtSecondRepayFail(String userId) {
        try {
            //由于代扣问题，部分还款成功，剩余未还金额，请重新操作还款。由此给您带来不便，敬请谅解,如有疑问请联系钱小二。
            //发送短信
            sendSmsDubboService.sendSmsByUserId(userId, SMSTemplateKeyEnum.TEMP_KAOLALICAI_BAD_DEBT_SECOND_REPAYMENT_FAIL.getKey(), null);

            //发送站内信
            UserLetterRequestDTO userLetterRequestDTO = new UserLetterRequestDTO();
            userLetterRequestDTO.setToUserId(userId);
            userLetterRequestDTO.setUserLetterTypeEnum(UserLetterTypeEnum.ONLY_LETTER);
            //站内信
            userLetterRequestDTO.setLetterTemplateEnum(MessageTemplateKeyEnum.LetterTemplateKeyEnum.TEMP_KAOLALICAI_BAD_DEBT_SECOND_REPAYMENT_FAIL);
            userLetterDubboService.pushLetter(userLetterRequestDTO);

        } catch (Exception e) {
            log.error("严重逾期-第2次还款失败消息通知（站内信和短信）-还款回调失败发送短信sendMsgForSecondBadDebtRepayFail-error", e);
        }
    }

    private KaoLaLiCaiRepayCallbackForKFTService getCurrentProxy() {
        return (KaoLaLiCaiRepayCallbackForKFTService) AopContext.currentProxy();
    }

    /**
     * 成功时除了代偿和回购其他的都要算清偿债权.
     *
     * @param kaolaRepayOrder 回调通知
     */
    public void updateCreditorStatus2Settlement(KaolaRepayOrder kaolaRepayOrder) {
        ProjectCreditorFund creditorFund = new ProjectCreditorFund();
        creditorFund.setProjectId(kaolaRepayOrder.getProjectId());

        // `repay_type` tinyint(4) DEFAULT NULL COMMENT '还款类型(1:正常还款,2:提前还款,3:逾期还款,4:严重逾期还款)'
        boolean notSettleOrBadDebt = !(kaolaRepayOrder.getRepayType().equals(KaoLaRepayOrderRepayTypeEnum.REPAY_SETTLE.getValue())
                || kaolaRepayOrder.getRepayType().equals(KaoLaRepayOrderRepayTypeEnum.REPAY_BADLOANS.getValue()));

        //不是提前结清或坏账还款则只更新当前期
        if (notSettleOrBadDebt) {
            if (Objects.isNull(kaolaRepayOrder.getRepayNo())) {
                creditorFund.setCurrentPeriod(100);
                //还款类型(1:正常还款,2:提前还款,3:逾期还款,4:严重逾期还款)
                log.error("考拉还款回调处理异常! 非结清的场景当前期为空,repayType:[{}]", kaolaRepayOrder.getRepayType());
            }
            creditorFund.setCurrentPeriod(kaolaRepayOrder.getRepayNo());
        }
        projectCreditorFundMapper.updateCreditorStatus2Settlement(creditorFund);

    }

    /**
     * 获取担保公司userId
     *
     * @return
     */
    private String getGuaranteeUserId() {
        return "" + lanMaoProperties.getNiiWooAccount().getGuaranteeUserId();
    }


    /**
     * 添加考拉账单
     *
     * @param kaoLaBill
     * @return
     */
    private void addKaoLaBill(AddThirdBillRequestDTO thirdBillRequestDTO, KaoLaBill kaoLaBill, KaolaDetailBill kaolaDetailBill) {
        // 账单主表，判断是否已赋值
        if (thirdBillRequestDTO.getUserId() == null) {
            thirdBillRequestDTO.setUserId(kaoLaBill.getUserId());
            thirdBillRequestDTO.setBillType(kaoLaBill.getBillUserTypeEnum());
            thirdBillRequestDTO.setRequestNo(kaoLaBill.getRequestNo());
            thirdBillRequestDTO.setAmount(kaoLaBill.getAmount());
            thirdBillRequestDTO.setInoutType(kaoLaBill.getInoutType());
            thirdBillRequestDTO.setProjectId(kaoLaBill.getProjectId());
            thirdBillRequestDTO.setChannelCodeEnum(com.niiwoo.civet.base.enums.ChannelCodeEnum.KAOLA);
            thirdBillRequestDTO.setRemark(kaoLaBill.getRemark());
        }

        // 账单明细表
        AddThirdBillRequestDTO.BillDetail billDetail = thirdBillRequestDTO.genertBillDetailInstance();
        billDetail.setRelationUserId(kaolaDetailBill.getUserId());
        billDetail.setAmount(kaolaDetailBill.getAmount());
        billDetail.setBillSecondSubjectEnum(kaolaDetailBill.getBillSecondSubjectEnum());
        billDetail.setCurrentPeriod(kaolaDetailBill.getCurrentPeriod());

        List<AddThirdBillRequestDTO.BillDetail> billDetailList = thirdBillRequestDTO.getBillDetailList();
        if (billDetailList == null) {
            thirdBillRequestDTO.setBillDetailList(new ArrayList<>());
        }
        thirdBillRequestDTO.getBillDetailList().add(billDetail);
    }

    @Setter
    @Getter
    @AllArgsConstructor
    private static class KaoLaBill {
        private String userId;// 用户
        private BillUserTypeEnum billUserTypeEnum;//账单用户类型枚举
        private String requestNo;//请求流水
        private BigDecimal amount;// 金额
        private InoutTypeEnum inoutType;// 收支类型
        private Long projectId;//项目ID
        private String remark;// 描述
    }

    @Setter
    @Getter
    @AllArgsConstructor
    private static class KaolaDetailBill {
        private String userId;// 关联用户
        private BigDecimal amount;// 金额
        private BillSecondSubjectEnum billSecondSubjectEnum;//账单二级类型
        private Integer currentPeriod;//当前期数
    }



    /**
     * @param kaolaRepayOrder
     * @param kaolaWithholdOrder
     * @Description 更新还款订单记录
     */
    private void updateKaolaRepayOrderSuccess(KaolaRepayOrder kaolaRepayOrder, KaolaWithholdOrder kaolaWithholdOrder) {
        KaolaRepayOrder kaolaRepayOrderForUpdate = new KaolaRepayOrder();
        kaolaRepayOrderForUpdate.setId(kaolaRepayOrder.getId());
        kaolaRepayOrderForUpdate.setRepayStatus(KaolaRepayOrderRepayStatusEnum.REPAY_SUCCESS.getValue());
        kaolaRepayOrderForUpdate.setUpdateTime(new Date());
        kaolaRepayOrderMapperExt.updateByPrimaryKeySelective(kaolaRepayOrderForUpdate);

        KaolaWithholdOrder kaolaWithholdOrderForUpdate = new KaolaWithholdOrder();
        kaolaWithholdOrderForUpdate.setId(kaolaWithholdOrder.getId());
        //	t_tc_kaola_withhold_order  `status` tinyint NOT NULL COMMENT '交易状态，1.交易成功，2.交易失败，3.交易处理中，4.异常成功，5.异常失败',
        kaolaWithholdOrderForUpdate.setStatus((byte) 1);
        kaolaWithholdOrderMapperExt.updateByPrimaryKeySelective(kaolaWithholdOrderForUpdate);
    }

    private void updateBorrowPlanDetailRefunedMoneyByFeeType(FeeTypeEnum feeTypeEnum, Long planId, BigDecimal refundMoney) {
        ProjectBorrowerPlanDetail projectBorrowerPlanDetail = projectBorrowerPlanDetailMapperExt.queryProjectBorrowerPlanDetailByPlanIdAndFeeType(planId, feeTypeEnum.getValue());
        ProjectBorrowerPlanDetail projectBorrowerPlanDetailForUpdate = new ProjectBorrowerPlanDetail();
        projectBorrowerPlanDetailForUpdate.setId(projectBorrowerPlanDetail.getId());
        projectBorrowerPlanDetailForUpdate.setRefundMoney(refundMoney);
        projectBorrowerPlanDetailForUpdate.setUpdateTime(new Date());
        projectBorrowerPlanDetailMapperExt.updateByPrimaryKeySelective(projectBorrowerPlanDetailForUpdate);

    }
}

